var createError = require('http-errors');
var express = require('express');
var router = express.Router();
var session = require('express-session');
// var MySQLStore = require('express-mysql-session')(session);
var FileStore = require('session-file-store')(session);
var fileUpload = require('express-fileupload');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var fs = require('fs');
var tools = require('./libs/tools');
var config = require(tools.rootPath + 'config');
var { connection, pool, model } = require(tools.rootPath + 'libs/model');
var app = express();

// view engine setup
app.set('views', path.join(tools.viewPath));
//app.set('view engine', 'ejs');
//https://www.zhaokeli.com/Article/6315.html
app.engine('.html', require('ejs').__express);
app.set('view engine', 'html');
// app.set('view cache', true);

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// app.use(express.static(path.join(__dirname, 'public')));

//http://www.ngrok.cc/
//wechat
//http://szh.vaiwan.com/wechat
//http://szh.free.idcfengye.com/wechat
var wechat_reply = require(tools.appPath + 'weixin/index.js');
app.use(express.query());
// app.use('/wechat', wechat({
//   token: 'szh2020',
//   appid: 'wxe9be79441cee423e',
//   encodingAESKey: '',
//   checkSignature: false // 可选，默认为true。由于微信公众平台接口调试工具在明文模式下不发送签名，所以如要使用该测试工具，请将其设置为false
// }, function (req, res, next) {
//   wechat_reply.index(req, res);
// }));
app.use('/wechat', require(tools.appPath + 'weixin/test.js'));

//session中间件
app.set('trust proxy', 1) // 信任代理
app.use(session({
  secret: 'szh2020',
  resave: false,
  saveUninitialized: false,
  // store: new MySQLStore({}, pool),
  store: new FileStore(),
}));

//上传中间件
app.use(fileUpload({
  limits: { fileSize: 2 * 1024 * 1024 },
  useTempFiles: true,
  tempFileDir: '/tmp/',
  createParentPath: true,
  parseNested: true,
  debug: false,
}));

//diy中间件
app.use(function (req, res, next) {
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Content-type', 'text/html;charset=utf-8');

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");

  let p = (req.baseUrl + req.path).split('/').splice(1);
  [req.CC, req.AA] = p;
  if (typeof (req.CC) == 'undefined' || req.CC == '') req.CC = 'index';
  if (typeof (req.AA) == 'undefined' || req.AA == '') req.AA = 'index';
  req.MM = req.CC = req.CC.toLowerCase();
  req.AA = req.AA.toLowerCase();

  console.log('visit:', req.MM, req.CC, req.AA);

  req.TPL = req.CC + '/' + req.AA;
  req.REQUEST_URI = (typeof (req.headers['referer']) != 'undefined' && req.headers['referer']) ? req.headers['referer'] : '';
  //console.log(req.REQUEST_URI);

  req.isPost = false;
  req.isGet = false;
  if (req.method == 'POST') req.isPost = true;
  if (req.method == 'GET') req.isGet = true;

  next();
});

app.route('*').all(async function (req, res, next) {
  //console.log('app.all',req.url);

  //判断类文件是否存在
  //这里也修改一下
  // let controllerFile = tools.controllerPath + req.MM + '/' + req.CC + '.js';
  let controllerFile = tools.controllerPath + req.CC + '.js';
  // console.log(controllerFile);
  if (!fs.existsSync(controllerFile)) {
    res.status(404);
    res.render('404', { msg: `controller file not exists!` + req.CC + '.js' });
    next();
    return;
  }
  var CC = require(controllerFile);
  let object = new CC();
  //初始化变量
  object.req = req;
  object.res = res;
  //调用初始化方法
  await object.init();
  //判断方法是否存在
  var methods = Object.getOwnPropertyNames(Object.getPrototypeOf(object));
  // console.log('controller methods list:', methods);
  //父亲的方法不会获取
  if (req.AA.indexOf('_') == 0) {
    res.status(404);
    res.render('404', { msg: `action not exists![a]` + req.AA });
    next();
    return;
  }
  var deny_list = ['constructor', 'init', 'msg', 'tpl', 'json', '__call', '__before', 'assign', 'session', 'redirect', 'post', 'get', 'isAjax', 'referer', 'model', 'action'];
  if (deny_list.indexOf(req.AA) > -1) {
    res.status(404);
    res.render('404', { msg: `action not exists![b]` + req.AA });
    next();
    return;
  }
  if (methods.indexOf(req.AA) == -1) {
    if (methods.indexOf('__call') > -1) {
      console.log('__call called!');

      //调用__before
      if (methods.indexOf('__before') > -1) {
        let result = await object['__before'](req, res);
        if (!result) {
          console.log('__before execute fail!');
          next();
          return;
        }
      }

      let result = await object['__call'](req, res);
      if (typeof (result) != 'undefined') {
        res.end(result.toString());
      }
      next();
      return;
    }
    res.status(404);
    res.render('404', { msg: `action not exists![c]` + req.AA });
    next();
    return;
  }
  //调用__before
  if (methods.indexOf('__before') > -1) {
    let result = await object['__before'](req, res);
    if (!result) {
      console.log('__before execute fail!');
      next();
      return;
    }
  }
  //调用方法并发送到浏览器
  let result = await object[req.AA](req, res);
  if (typeof (result) != 'undefined') {
    res.end(result.toString());
  }
  next();
});

// catch 404 and forward to error handler
// app.use(function (req, res, next) {
//   next(createError(404));
// });

// error handler
// app.use(function (err, req, res, next) {
//   // set locals, only providing error in development
//   res.locals.message = err.message;
//   res.locals.error = req.app.get('env') === 'development' ? err : {};

//   // render the error page
//   res.status(err.status || 500);
//   res.render('error');
// });

module.exports = app;
